﻿namespace SPWikiProvisioning.Extensions
{
    #region Usings

    using System;
    using System.Collections;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Web.UI.WebControls.WebParts;
    using System.Xml;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebPartPages;

    using SPWikiProvisioning.Model;

    using WebPart = System.Web.UI.WebControls.WebParts.WebPart;

    #endregion

    internal static class SPWikiPageExtensions
    {
        internal static void ProvisionWikiPage(this SPFile wikiPage, string content, Hashtable webPartsCollection, bool isDefault)
        {
            if (wikiPage == null)
            {
                throw new ArgumentNullException("wikiPage");
            }

            SPListItem listItem = wikiPage.GetListItem(new[] { "WikiField" });
            if (listItem == null)
            {
                throw new ArgumentException(SPResource.GetString("OnlyInWikiLibraries", new object[0]));
            }

            SPList parentList = listItem.ParentList;
            if (parentList == null || parentList.BaseTemplate != SPListTemplateType.WebPageLibrary)
            {
                throw new ArgumentException(SPResource.GetString("OnlyInWikiLibraries", new object[0]));
            }

            using (SPLimitedWebPartManager limitedWebPartManager = wikiPage.GetLimitedWebPartManager(PersonalizationScope.Shared))
            {
                var existingWebParts = limitedWebPartManager.WebParts;
                var existingWebPartsList = existingWebParts.Cast<WebPart>().ToList();

                foreach (WebPart existingWebpart in existingWebPartsList)
                {
                    limitedWebPartManager.DeleteWebPart(existingWebpart);
                }

                var webparts = webPartsCollection.GetEnumerator();
                while (webparts.MoveNext())
                {
                    if (webparts.Current != null)
                    {
                        var entry = (DictionaryEntry)webparts.Current;
                        var provisionedWebPart = (ProvisionedWebPart)webPartsCollection[entry.Key];
                        var webpartcontent = provisionedWebPart.WebPartContent;

                        string message;
                        var reader = new XmlTextReader(new StringReader(webpartcontent));
                        var webPart = limitedWebPartManager.ImportWebPart(reader, out message);

                        var storageKey = new Guid(entry.Key.ToString());
                        string wpId = String.Format(CultureInfo.CurrentCulture, "g_{0}", storageKey.ToString().Replace('-', '_'));
                        webPart.ID = wpId;
                        SetWebPartAudience(limitedWebPartManager, provisionedWebPart, webPart);

                        limitedWebPartManager.AddWebPart(webPart, "wpz", 0);



                        string marker = String.Format(CultureInfo.InvariantCulture, "<div class=\"ms-rtestate-read ms-rte-wpbox\" contentEditable=\"false\"><div class=\"ms-rtestate-read {0}\" id=\"div_{0}\"></div><div style='display:none' id=\"vid_{0}\"></div></div>", new object[] { storageKey.ToString("D") });

                        content = content.Replace(String.Format(CultureInfo.CurrentCulture, "<WebPart id='{0}'/>", storageKey.ToString("D")), marker);
                    }
                }

                content = content.Replace("~SiteCollection", limitedWebPartManager.Web.Site.Url);
                content = content.Replace("~Site", limitedWebPartManager.Web.Url);

                listItem["WikiField"] = content;
                listItem.UpdateOverwriteVersion();
            }

            if (isDefault)
            {
                var rootFolder = wikiPage.Web.RootFolder;
                rootFolder.WelcomePage = wikiPage.Web.ServerRelativeUrl == "/" ?
                    wikiPage.ServerRelativeUrl.Substring(1) : 
                    wikiPage.ServerRelativeUrl.Replace(wikiPage.Web.ServerRelativeUrl + "/", String.Empty);
                rootFolder.Update();
            }
        }

        private static void SetWebPartAudience(
            SPLimitedWebPartManager limitedWebPartManager, ProvisionedWebPart provisionedWebPart, WebPart webPart)
        {
            var audience = provisionedWebPart.WebPartAudience;
            if (!String.IsNullOrEmpty(audience))
            {
                switch (audience)
                {
                    case "Owners":
                        webPart.AuthorizationFilter = ";;;;" + limitedWebPartManager.Web.AssociatedOwnerGroup.Name;
                        break;
                    case "Members":
                        webPart.AuthorizationFilter = ";;;;" + limitedWebPartManager.Web.AssociatedMemberGroup.Name;
                        break;
                    case "Visitors":
                        webPart.AuthorizationFilter = ";;;;" + limitedWebPartManager.Web.AssociatedVisitorGroup.Name;
                        break;
                    default:
                        webPart.AuthorizationFilter = ";;;;" + audience;
                        break;
                }
            }
        }
    }
}
